#ifndef MQTTCOMMON_HPP
#define MQTTCOMMON_HPP

#include <string>
#include <iostream>
#include <chrono>
#include <functional>
#include <vector>
#include <ctime>
#include <cassert>
#include <cstdarg>
#include <sstream>
#include <XLogger.hpp>

using namespace std;
using namespace std::chrono;
using namespace std::chrono_literals;

struct Msg;
struct timedTaskStruct;
class MqttClient;

using MqttReceiveParseMsgCallback = std::function<void(const Msg&)>;
using MqttMsgParseInitCallback = std::function<void(const std::shared_ptr<MqttClient>&)>;


struct Msg {
	std::string topic;
	std::string payload;
	int qos;

	Msg(const std::string& top, const std::string& payload, int qos = 0)
		: topic(top), payload(payload), qos(qos) {
	}

	Msg(const std::string&& top, const std::string&& payload, int qos = 0)
		: topic(top), payload(payload), qos(qos) {
	}

	friend std::ostream &operator<<(std::ostream& os, const Msg& msg) {
		//LOG_DEBUG("topic: {} qos: {} payload: {}", msg.topic, msg.qos, msg.payload);
		return os;
	}
};


uint64_t getLocalTimeStampUs() {
	return std::chrono::duration_cast<std::chrono::microseconds>(
		std::chrono::system_clock::now().time_since_epoch()).count();
}

uint64_t getLocalTimeStampMs() {
	return std::chrono::duration_cast<std::chrono::milliseconds>(
		std::chrono::system_clock::now().time_since_epoch()).count();
}

uint64_t getLocalTimeStampS() {
	return std::chrono::duration_cast<std::chrono::seconds>(
		std::chrono::system_clock::now().time_since_epoch()).count();
}

template<class Rep, class Period>
std::chrono::duration<long, std::micro> formatToSystemTimeStampMs(std::chrono::duration<Rep, Period> time) {
	return std::chrono::duration_cast<std::chrono::microseconds>(time);
}

/* 计算两个相同字符之间的长度（跳过前几个字符）*/
size_t countDistance(const std::string& str, char c, size_t skipCount = 0) {
	size_t count = 0;
	size_t pos = str.find(c);
	size_t skip = 0;

	while (pos != std::string::npos) {
		if (skip >= skipCount) {
			size_t nextPos = str.find(c, pos + 1);
			if (nextPos != std::string::npos) {
				count += nextPos - pos - 1;
				pos = nextPos;
			} else {
				break;
			}
		} else {
			++skip;
			pos = str.find(c, pos + 1);
		}
	}

	return count;
}

class MqttConnectInfo {
public:
	std::string server;
	int port;
	std::string clientID;
	std::string user;
	std::string passwd;
	bool cleanSession;
	int keepAlive;
};

#endif //MQTTCOMMON_HPP
